﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using WhallaToolkit.ShareServices.Interfaces;
using WhallaToolkit.ShareServices.Models.AccessTokens;
using TweetSharp;
using WhallaToolkit.ShareServices.Exceptions;

namespace WhallaToolkit.ShareServices.Services
{
    public class TwitterServices : IShareService
    {
        #region Fields

        TaskCompletionSource<bool> twitterDataResult = new TaskCompletionSource<bool>();

        #endregion

        #region Properties
        public AccessToken Token { get; set; }
        
        #endregion

        #region Constructor        
        public TwitterServices()
        {

        }

        #endregion

        #region Methods

        internal static Uri GetLoginUrl(OAuthRequestToken token)
        {
            return new Uri("https://api.twitter.com/oauth/authorize" + "?oauth_token=" + token.Token + "&style=mobile", UriKind.RelativeOrAbsolute);
        }

        private async Task<bool> PostMediaOnTwitterAsync(Stream photoSource, string description)
        {

            if (Token != null && !string.IsNullOrEmpty(Token.Token) && !string.IsNullOrEmpty((((TwitterAccessToken)Token).TokenSecret)))
                {
                    TwitterService service = new TwitterService(PortalsResources.TwitterConsumerKey, PortalsResources.TwitterConsumerSecret);
                    service.AuthenticateWith(Token.Token, ((TwitterAccessToken)Token).TokenSecret);

                    IDictionary<string, Stream> list = new Dictionary<string, Stream>();
                    photoSource.Seek(0, SeekOrigin.Begin);
                    list.Add("media", photoSource);
                    SendTweetWithMediaOptions options = new SendTweetWithMediaOptions
                    {
                        Status = description,
                        Images = list
                    };

                    service.SendTweetWithMedia(options,
                                (s, resp) =>
                                {
                                    if (resp != null)
                                    {
                                        if (resp.StatusCode == HttpStatusCode.Forbidden || resp.StatusCode == HttpStatusCode.Unauthorized)
                                        {
                                            throw new UnauthorizedException();
                                        }
                                        if (resp.StatusCode == HttpStatusCode.NotFound)
                                        {
                                            twitterDataResult.SetResult(false);
                                        }
                                        else if (resp.StatusCode == HttpStatusCode.OK)
                                        {
                                            twitterDataResult.SetResult(true);
                                        }
                                    }
                                });
                }

            return await twitterDataResult.Task;
        }

        private async Task<bool> PostMediaOnTwitterAsync(BitmapImage photoSource, string description)
        {

            if (Token != null && !string.IsNullOrEmpty(Token.Token) && !string.IsNullOrEmpty(((TwitterAccessToken)Token).TokenSecret))
            {
                TwitterService service = new TwitterService(PortalsResources.TwitterConsumerKey, PortalsResources.TwitterConsumerSecret);
                service.AuthenticateWith(Token.Token, ((TwitterAccessToken)Token).TokenSecret);

                IDictionary<string, Stream> list = new Dictionary<string, Stream>();

                WriteableBitmap bmp = new WriteableBitmap(photoSource);
                Stream imageStream = new MemoryStream();
                bmp.SaveJpeg(imageStream, photoSource.PixelWidth, photoSource.PixelHeight, 0, 100);
                imageStream.Seek(0, SeekOrigin.Begin);

                list.Add("media", imageStream);
                SendTweetWithMediaOptions options = new SendTweetWithMediaOptions
                {
                    Status = description,
                    Images = list
                };

                service.SendTweetWithMedia(options,
                            (s, resp) =>
                            {
                                if (resp != null)
                                {
                                    if (resp.StatusCode == HttpStatusCode.Forbidden || resp.StatusCode == HttpStatusCode.Unauthorized)
                                    {
                                        throw new UnauthorizedException();
                                    }
                                    if (resp.StatusCode == HttpStatusCode.NotFound)
                                    {
                                        twitterDataResult.SetResult(false);
                                    }
                                    else if (resp.StatusCode == HttpStatusCode.OK)
                                    {
                                        twitterDataResult.SetResult(true);
                                    }
                                }
                            });
            }

            return await twitterDataResult.Task;
        }

        private async Task<bool> PostMessageOnTwitterAsync(string description)
        {

            if (Token != null && !string.IsNullOrEmpty(Token.Token) && !string.IsNullOrEmpty(((TwitterAccessToken)Token).TokenSecret))
            {
                TwitterService service = new TwitterService(PortalsResources.TwitterConsumerKey, PortalsResources.TwitterConsumerSecret);
                service.AuthenticateWith(Token.Token, ((TwitterAccessToken)Token).TokenSecret);
                description = description.Substring(0, 140);
                SendTweetOptions options = new SendTweetOptions()
                {
                    Status = description
                };
                
                service.SendTweet(options, (s, resp) =>
                {
                    if (resp != null)
                    {
                        if (resp.StatusCode == HttpStatusCode.Forbidden || resp.StatusCode == HttpStatusCode.Unauthorized)
                        {
                            throw new UnauthorizedException();
                        }
                        if (resp.StatusCode == HttpStatusCode.NotFound)
                        {
                            twitterDataResult.SetResult(false);
                        }
                        else if (resp.StatusCode == HttpStatusCode.OK)
                        {
                            twitterDataResult.SetResult(true);
                        }
                    }
                });
            }

            return await twitterDataResult.Task;
        }

        private async Task<bool> PostLinkOnTwitterAsync(string link, string description)
        {
            if (Token != null && !string.IsNullOrEmpty(Token.Token) && !string.IsNullOrEmpty(((TwitterAccessToken)Token).TokenSecret))
            {
                TwitterService service = new TwitterService(PortalsResources.TwitterConsumerKey, PortalsResources.TwitterConsumerSecret);
                service.AuthenticateWith(Token.Token, ((TwitterAccessToken)Token).TokenSecret);
                link += "\n"+description;
                link = link.Substring(0, 140);
                SendTweetOptions options = new SendTweetOptions()
                {
                    Status = link
                };

                service.SendTweet(options, (s, resp) =>
                {
                    if (resp != null)
                    {
                        if (resp.StatusCode == HttpStatusCode.Forbidden || resp.StatusCode == HttpStatusCode.Unauthorized)
                        {
                            throw new UnauthorizedException();
                        }
                        if(resp.StatusCode == HttpStatusCode.NotFound)
                        {
                            twitterDataResult.SetResult(false);
                        }
                        else if (resp.StatusCode == HttpStatusCode.OK)
                        {
                            twitterDataResult.SetResult(true);
                        }
                    }
                });
            }

            return await twitterDataResult.Task;
        } 

        #endregion

        #region Interface Methods
        public void SetToken(AccessToken tokens)
        {
            Token = tokens;
        }

        public async Task<bool> PostMediaOnSocialTask(AccessToken tokens, Stream photoSource, string description)
        {
                Token = (TwitterAccessToken)tokens;
                return await PostMediaOnTwitterAsync(photoSource, description);
        }

        public async Task<bool> PostMediaOnSocialTask(Stream photoSource, string description)
        {
            return await PostMediaOnTwitterAsync(photoSource, description);
        }

        public async Task<bool> PostMediaOnSocialTask(AccessToken tokens, BitmapImage photoSource, string description)
        {
            Token = (TwitterAccessToken)tokens;
            return await PostMediaOnTwitterAsync(photoSource, description);
        }

        public async Task<bool> PostMediaOnSocialTask(BitmapImage photoSource, string description)
        {
            return await PostMediaOnTwitterAsync(photoSource, description);
        }

        public async Task<bool> PostMessageOnSocialTask(string description)
        {
            return await PostMessageOnTwitterAsync(description);
        }

        public async Task<bool> PostLinkOnSocialTask(AccessToken tokens, string link, string description)
        {
            Token = (TwitterAccessToken)tokens;
            return await PostLinkOnSocialTask(link, description);
        }
        public async Task<bool> PostLinkOnSocialTask(string link, string description)
        {
            return await PostLinkOnTwitterAsync(link, description);
        }
        #endregion
    }
}
